package com.lipaluma.field.validator.impl.date;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.lipaluma.Xml;
import com.lipaluma.annotations.validations.ValidateDate;
import com.lipaluma.context.Context;
import com.lipaluma.exceptions.CsvParserException;
import com.lipaluma.field.validator.impl.generic.AbstractIsExcludedOfValidator;
import com.lipaluma.util.ParserUtils;
import com.lipaluma.xml.validator.XmlExcludedOfValidator;
import com.lipaluma.xml.validator.XmlValidator;

/**
 * Validate a {@link Date} field to check if the date value extracted must be excluded of the differents given values.<br/>
 * 
 * <p>
 * For Initialisation :
 * <ul>
 * 	<li>
 * 	<u><b>By annotations :</b></u> Use {@link ValidateDate}, with the attribute <code>excludedOf = {"2013-10-15", "..."}</code> to specify the list of
 * values rejected. <br/>
 * Beware ! the attribute <code>pattern</code> is mandatory to resolve the parsing of given dates.
 * </li>
 * 	<li>
 * 	<u><b>By Xml :</b></u>
 * <ul>
 * <li>
 * This validator can be added using xml mapping with the element <code>excludedOf</code> like below : <br/>
 * <code>
 * &lt;ToMap field="..."   ...><br/>
 * <b>
 * &nbsp;&nbsp;&nbsp;&lt;excludedOf pattern="yyyy-MM-dd"><br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value>2013-10-05&lt;/value><br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value>2013-10-07&lt;/value><br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value>2013-10-09&lt;/value><br/>
 * &nbsp;&nbsp;&nbsp;&lt;/excludedOf>
 * </b><br/>
 * &lt;/ToMap>
 * </code>
 * <br/>
 * Take care of the mandatory attribute pattern used to parse the date value given.
 * </li>
 * </li>
 * </ul>
 * @author Mario
 *
 */
public class DateExcludedOfValidator extends AbstractIsExcludedOfValidator<Date> {

	public DateExcludedOfValidator() {}
	public DateExcludedOfValidator(Date... values) {
		if(values == null)
			throw new CsvParserException("Error on setting "+this.getClass()+" : given values can't be null");
		init(Arrays.asList(values));		
	}

	@Override
	public boolean init(Context context, Field field) {
		ValidateDate annotation = field.getAnnotation(ValidateDate.class);
		if(annotation == null || annotation.excludedOf().length == 0)
			return false;
		String pattern = annotation.pattern();
		if(pattern.isEmpty())
			throw new CsvParserException("Error on field "+field.getName()+" : The annotation ValidateDate must have a non empty pattern.");
		
		List<Date> excludedDates = new ArrayList<Date>();
		for(String string : annotation.excludedOf()) {
			excludedDates.add((Date)ParserUtils.parseToType(field.getType(), string, pattern));
		}
		init(excludedDates);
		return true;
	}
	
	@Override
	public boolean init(Context context, Field field, XmlValidator xmlValidator) {
		XmlExcludedOfValidator validator = (XmlExcludedOfValidator)xmlValidator;
		String pattern = validator.getPattern();
		if(StringUtils.isEmpty(pattern))
			throw new CsvParserException("Error on field "+field.getName()+" : The "+Xml.EXCLUDED_OF+" validator element must have a valid '"+Xml.PATTERN+"' attribute");
		
		List<Date> excludedDates = new ArrayList<Date>();
		for(String value : validator.getValues()) {
			excludedDates.add((Date)ParserUtils.parseToType(field.getType(), value, pattern)); 
		}
		init(excludedDates);
		return true;
	}

	
}
